/**
 * @file overturn_detect_c2.c
 * @brief ESP32-C2加速度检测振动和雾化加湿反馈执行装置
 *
 * 本项目实现了一个基于ESP32-C2的智能手势识别和反馈系统：
 * 1. 通过SC7A20H IMU传感器读取三轴加速度数据
 * 2. 使用状态机进行数据滤波和运动模式识别
 * 3. 检测手掌的翻转、左右移动、前后移动等手势
 * 4. 通过振动马达和雾化器提供触觉和喷雾反馈
 *
 * 主要功能模块：
 * - 加速度数据采集和滤波
 * - 运动状态机检测算法
 * - 振动马达控制（3个马达）
 * - 雾化器喷雾控制
 * - 电池电压监测和LED指示
 *
 * @author Simon
 * @date 2024
 */

#include <stdio.h>
#include <string.h>

#include "driver/gpio.h"
#include "driver/ledc.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_gatts_api.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "nvs_flash.h"

#include "sc7a20h.h"
#include "pm.h"
#include "motor.h"
#include "atomizer.h"
#include "ble.h"
#include "main.h"

#define TAG "APP"

// ==================== 动作检测参数配置 ====================
#define MOTION_DETECT_SAMPLES        20   // 加速度数据保存窗口大小，用于滑动平均计算
#define MOTION_AVERAGE_WINDOW_SIZE   5    // 计算平均加速度需要的采样数
#define MOTION_MOTION_THRESHOLD      1024 // 运动检测阈值：1024/8192 = 0.125g = 1.225 m/s²
#define MOTION_X_OFFSET              200  // X轴偏移补偿值，用于提高X轴触发灵敏度
#define MOTION_DELTA_ACCEL_THRESHOLD 512  // 加速度变化阈值：512/8192 = 0.0625g = 0.6125 m/s²
#define MOTION_DELTA_SLOW_THRESHOLD  512  // 减速检测阈值：512/8192 = 0.0625g = 0.6125 m/s²
#define MOTION_DELTA_TIME_MS         20   // 检测周期：20ms (50Hz采样率)
#define MOTION_NG_TIME_MS            40   // 检测失败超时时间
#define MOTION_ACCEL_TIME_MS         80   // 加速度确认时间
#define MOTION_TRANSFER_TIMEOUT_MS   500  // 状态转换超时时间
#define MOTION_SLOW_TIME_MS          40   // 减速确认时间
#define MOTION_STABLE_TIMEOUT_MS     100  // 稳定状态确认时间
#define MOTION_FLIP_TIME_MS          200  // 翻转检测时间

// static void example_write_event_env(esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);

/**
 * @brief 手掌动作类型枚举
 */
typedef enum
{
    PAW_ACTION_NONE,     // 无动作
    PAW_ACTION_FLIP,     // 翻转动作
    PAW_ACTION_LEFT,     // 向左移动
    PAW_ACTION_RIGHT,    // 向右移动
    PAW_ACTION_FORWARD,  // 向前移动
    PAW_ACTION_BACKWARD, // 向后移动
} paw_state_t;

/**
 * @brief 运动检测状态机状态枚举
 */
typedef enum
{
    MOTION_STATE_STABLE,          // 稳定状态：等待运动开始
    MOTION_STATE_ACCEL_DETECTING, // 加速度检测状态：检测运动开始
    MOTION_STATE_WAIT_SLOW,       // 等待减速状态：等待运动减速
    MOTION_STATE_SLOW_DETECTING,  // 减速检测状态：检测运动结束
    MOTION_STATE_WAIT_STABLE      // 等待稳定状态：等待回到稳定
} motion_state_t;

/**
 * @brief 运动方向枚举
 */
typedef enum
{
    MOTION_DIRECT_X_POS, // X轴正方向
    MOTION_DIRECT_X_NEG, // X轴负方向
    MOTION_DIRECT_Y_POS, // Y轴正方向
    MOTION_DIRECT_Y_NEG, // Y轴负方向
    MOTION_DIRECT_Z_POS, // Z轴正方向
    MOTION_DIRECT_Z_NEG, // Z轴负方向
} motion_direct_t;

/**
 * @brief 翻转状态枚举
 */
typedef enum
{
    FLIP_POS, // 正面朝上
    FLIP_NEG, // 正面朝下
} flip_state_t;

/**
 * @brief 三轴加速度数据结构
 */
typedef struct
{
    int16_t x; // X轴加速度值
    int16_t y; // Y轴加速度值
    int16_t z; // Z轴加速度值
} accel_data_t;

/**
 * @brief 运动检测数据结构
 * 包含状态机所需的所有状态变量和数据缓存
 */
typedef struct
{
    int16_t         x_avg, y_avg, z_avg;                 // 平均加速度值
    accel_data_t    accel_now;                           // 当前加速度数据
    accel_data_t    accel_window[MOTION_DETECT_SAMPLES]; // 加速度数据滑动窗口
    uint8_t         window_index;                        // 窗口索引
    motion_state_t  motion_state;                        // 当前运动状态
    motion_direct_t motion_direct;                       // 检测到的运动方向
    uint32_t        pass_timing;                         // 检测通过计时器
    uint32_t        fail_timing;                         // 检测失败计时器
    flip_state_t    flip_state;                          // 翻转状态
    uint32_t        flip_timing;                         // 翻转检测计时器
} motion_detection_t;

// ==================== 全局变量 ====================

static esp_timer_handle_t motion_detect_timer;   // 运动检测定时器句柄
static motion_detection_t motion_detector = {0}; // 运动检测器实例

static paw_state_t       paw_state = PAW_ACTION_NONE; // 当前检测到的手掌动作
static SemaphoreHandle_t paw_action_sem;              // 动作信号量


// ==================== 运动检测算法 ====================

/**
 * @brief 计算滑动窗口内加速度的平均值
 * @param detector 运动检测器指针
 */
static void imu_calculate_average(motion_detection_t *detector)
{
    int32_t sum_x = 0, sum_y = 0, sum_z = 0;

    // 确保有足够的数据进行平均计算
    if (detector->window_index < MOTION_AVERAGE_WINDOW_SIZE) {
        return;
    }

    // 计算最近MOTION_AVERAGE_WINDOW_SIZE个样本的平均值
    for (int i = 0; i < MOTION_AVERAGE_WINDOW_SIZE; i++) {
        int idx = (detector->window_index + MOTION_DETECT_SAMPLES - i) % MOTION_DETECT_SAMPLES;
        sum_x += detector->accel_window[idx].x;
        sum_y += detector->accel_window[idx].y;
        sum_z += detector->accel_window[idx].z;
    }

    detector->x_avg = sum_x / MOTION_AVERAGE_WINDOW_SIZE;
    detector->y_avg = sum_y / MOTION_AVERAGE_WINDOW_SIZE;
    detector->z_avg = sum_z / MOTION_AVERAGE_WINDOW_SIZE;

    // ESP_LOGI(TAG, "avg: x=%d, y=%d, z=%d\n", detector->x_avg, detector->y_avg, detector->z_avg);
}

/**
 * @brief 检测是否处于稳定状态
 * @param detector 运动检测器指针
 * @param threshold 稳定检测阈值
 * @return true稳定，false不稳定
 */
static bool is_stable(motion_detection_t *detector, int16_t threshold)
{
    // 确保有足够的样本数据
    uint8_t index = detector->window_index;
    if (index <= MOTION_AVERAGE_WINDOW_SIZE)
        return true;

    // 计算当前值与平均值的差值
    int16_t dx = detector->accel_window[index].x - detector->x_avg;
    int16_t dy = detector->accel_window[index].y - detector->y_avg;
    int16_t dz = detector->accel_window[index].z - detector->z_avg;

    // printf("current: x=%d, y=%d, z=%d, avg: x=%d, y=%d, z=%d\n",
    //        current_x, current_y, current_z, detector->x_avg, detector->y_avg, detector->z_avg);
    // printf("dx: %d, dy: %d, dz: %d\n", dx, dy, dz);

    // 检查是否所有轴的差值都在阈值范围内（X轴使用较小的阈值）
    if ((abs(dx) <= threshold - MOTION_X_OFFSET * 2) && abs(dy) <= threshold && abs(dz) <= threshold) {
        return true;
    }

    // 确定运动方向（选择变化最大的轴）
    int16_t abs_dx = abs(dx);
    int16_t abs_dy = abs(dy);
    int16_t abs_dz = abs(dz);

    int16_t abs_max = 0;
    if (abs_dx >= abs_dy) {
        abs_max = abs_dx;
    } else {
        abs_max = abs_dy;
    }
    if (abs_max < abs_dz) {
        abs_max = abs_dz;
    }

    // 根据最大变化轴确定运动方向
    if (abs_max == abs_dx) {
        detector->motion_direct = (dx > 0) ? MOTION_DIRECT_X_POS : MOTION_DIRECT_X_NEG;
    } else if (abs_max == abs_dy) {
        detector->motion_direct = (dy > 0) ? MOTION_DIRECT_Y_POS : MOTION_DIRECT_Y_NEG;
    } else {
        detector->motion_direct = (dz > 0) ? MOTION_DIRECT_Z_POS : MOTION_DIRECT_Z_NEG;
    }
    ESP_LOGI(TAG, "direct: %d", detector->motion_direct);

    return false;
}

/**
 * @brief 检测是否持续稳定
 * @param detector 运动检测器指针
 * @param threshold 稳定检测阈值
 * @return true持续稳定，false不稳定
 */
static bool is_stable_keep(motion_detection_t *detector, int16_t threshold)
{
    // 确保有足够的样本数据
    if (detector->window_index <= MOTION_AVERAGE_WINDOW_SIZE)
        return true;

    int16_t dx, dy, dz;
    for (uint8_t i = 0; i < MOTION_STABLE_TIMEOUT_MS / MOTION_DELTA_TIME_MS; i++) {
        uint8_t index      = (detector->window_index - i) % MOTION_DETECT_SAMPLES;
        uint8_t index_prev = (index - 1) % MOTION_DETECT_SAMPLES;
        // 计算与平均值的差值
        dx = detector->accel_window[index].x - detector->accel_window[index_prev].x;
        dy = detector->accel_window[index].y - detector->accel_window[index_prev].y;
        dz = detector->accel_window[index].z - detector->accel_window[index_prev].z;

        if (abs(dx) > threshold || abs(dy) > threshold || abs(dz) > threshold) {
            return false;
        }
    }
    return true;
}

/**
 * @brief 检测加速度变化是否符合预期方向
 * @param detector 运动检测器指针
 * @param threshold 加速度检测阈值
 * @return true检测到加速度变化，false未检测到
 *
 * 该函数根据已确定的运动方向，检测当前加速度值是否在预期方向上超过阈值。
 * 如果检测到加速度变化，会增加pass_timing计时器；否则增加fail_timing计时器。
 */
static bool is_motion_accel(motion_detection_t *detector, int16_t threshold)
{
    bool    is_accel = false;
    uint8_t index    = detector->window_index;

    // 根据运动方向检测加速度变化
    switch (detector->motion_direct) {
    case MOTION_DIRECT_X_POS:
        // X轴正方向：检测X轴加速度是否正向超过阈值
        if (detector->accel_window[index].x - detector->x_avg > (threshold - MOTION_X_OFFSET))
            is_accel = true;
        break;
    case MOTION_DIRECT_X_NEG:
        // X轴负方向：检测X轴加速度是否负向超过阈值
        if (detector->accel_window[index].x - detector->x_avg < -(threshold - MOTION_X_OFFSET))
            is_accel = true;
        break;
    case MOTION_DIRECT_Y_POS:
        // Y轴正方向：检测Y轴加速度是否正向超过阈值
        if (detector->accel_window[index].y - detector->y_avg > threshold)
            is_accel = true;
        break;
    case MOTION_DIRECT_Y_NEG:
        // Y轴负方向：检测Y轴加速度是否负向超过阈值
        if (detector->accel_window[index].y - detector->y_avg < -threshold)
            is_accel = true;
        break;
    case MOTION_DIRECT_Z_POS:
        // Z轴正方向：检测Z轴加速度是否正向超过阈值
        if (detector->accel_window[index].z - detector->z_avg > threshold)
            is_accel = true;
        break;
    case MOTION_DIRECT_Z_NEG:
        // Z轴负方向：检测Z轴加速度是否负向超过阈值
        if (detector->accel_window[index].z - detector->z_avg < -threshold)
            is_accel = true;
        break;
    }

    // 更新检测计时器
    if (is_accel) {
        detector->pass_timing += MOTION_DELTA_TIME_MS; // 检测成功，增加通过计时
    } else {
        detector->fail_timing += MOTION_DELTA_TIME_MS; // 检测失败，增加失败计时
    }

    return is_accel;
}

/**
 * @brief 检测减速变化是否符合预期方向
 * @param detector 运动检测器指针
 * @param threshold 减速检测阈值
 * @return true检测到减速变化，false未检测到
 *
 * 该函数检测运动结束时的减速过程，与is_motion_accel相反，
 * 检测加速度是否在相反方向上超过阈值。
 */
static bool is_motion_slow(motion_detection_t *detector, int16_t threshold)
{
    bool    is_slow = false;
    uint8_t index   = detector->window_index;

    // 根据运动方向检测减速变化（与加速度方向相反）
    switch (detector->motion_direct) {
    case MOTION_DIRECT_X_POS:
        // X轴正方向运动结束：检测X轴是否向负方向减速
        if (detector->accel_window[index].x - detector->x_avg < -(threshold - MOTION_X_OFFSET))
            is_slow = true;
        break;
    case MOTION_DIRECT_X_NEG:
        // X轴负方向运动结束：检测X轴是否向正方向减速
        if (detector->accel_window[index].x - detector->x_avg > (threshold - MOTION_X_OFFSET))
            is_slow = true;
        break;
    case MOTION_DIRECT_Y_POS:
        // Y轴正方向运动结束：检测Y轴是否向负方向减速
        if (detector->accel_window[index].y - detector->y_avg < -threshold)
            is_slow = true;
        break;
    case MOTION_DIRECT_Y_NEG:
        // Y轴负方向运动结束：检测Y轴是否向正方向减速
        if (detector->accel_window[index].y - detector->y_avg > threshold)
            is_slow = true;
        break;
    case MOTION_DIRECT_Z_POS:
        // Z轴正方向运动结束：检测Z轴是否向负方向减速
        if (detector->accel_window[index].z - detector->z_avg < -threshold)
            is_slow = true;
        break;
    case MOTION_DIRECT_Z_NEG:
        // Z轴负方向运动结束：检测Z轴是否向正方向减速
        if (detector->accel_window[index].z - detector->z_avg > threshold)
            is_slow = true;
        break;
    }

    // 更新检测计时器
    if (is_slow) {
        detector->pass_timing += MOTION_DELTA_TIME_MS; // 检测成功，增加通过计时
    } else {
        detector->fail_timing += MOTION_DELTA_TIME_MS; // 检测失败，增加失败计时
    }

    return is_slow;
}

/**
 * @brief 发送手掌动作信号
 * @param detector 运动检测器指针
 *
 * 根据检测到的运动状态和方向，设置相应的手掌动作类型，
 * 并通过信号量通知响应任务执行相应的反馈动作。
 */
void send_paw_action(motion_detection_t *detector)
{
    if (detector->motion_state == MOTION_STATE_SLOW_DETECTING) {
        // 在减速检测状态下，根据运动方向确定具体的手势类型
        switch (detector->motion_direct) {
        case MOTION_DIRECT_X_NEG:
            paw_state = PAW_ACTION_FORWARD; // X轴负方向 = 向前移动
            break;
        case MOTION_DIRECT_Y_POS:
            paw_state = PAW_ACTION_LEFT; // Y轴正方向 = 向左移动
            break;
        case MOTION_DIRECT_Y_NEG:
            paw_state = PAW_ACTION_RIGHT; // Y轴负方向 = 向右移动
            break;
        default:
            break;
        }
    } else {
        // 其他状态下默认为翻转动作
        paw_state = PAW_ACTION_FLIP;
    }

    // 发送信号量通知响应任务
    xSemaphoreGive(paw_action_sem);
}

/**
 * @brief 运动检测定时器回调函数
 * @param arg 回调参数（运动检测器指针）
 *
 * 这是运动检测的核心函数，每20ms执行一次：
 * 1. 读取IMU加速度数据
 * 2. 更新数据滑动窗口
 * 3. 执行状态机逻辑
 * 4. 检测翻转动作
 */
void motion_detect_callback(void *arg)
{
    motion_detection_t *detector = (motion_detection_t *)arg;
    int16_t             x, y, z;

    // 读取IMU三轴加速度数据
    esp_err_t err = sc7a20h_read_accel(&x, &y, &z);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "failed to read accel");
        return;
        // } else {
        //     printf("x: %d, y: %d, z: %d\n", x, y, z);
    }

    // 将当前加速度数据存入滑动窗口
    detector->accel_now.x = x;
    detector->accel_now.y = y;
    detector->accel_now.z = z;
    detector->accel_window[detector->window_index] = detector->accel_now;

    // 大约每100ms通过BLE上报一次数据
    static uint32_t last_notify_time = 0;
    uint32_t current_time = xTaskGetTickCount() * portTICK_PERIOD_MS;
    if (current_time - last_notify_time >= 100) {
        last_notify_time = current_time;
        // 先将加速度数据拷贝到imu_data_val数组（BLE特征值缓冲区）
        memcpy(imu_data_val, &detector->accel_now, sizeof(detector->accel_now));
        // 然后更新BLE特征值，这会触发ESP_GATTS_SET_ATTR_VAL_EVT事件
        esp_ble_gatts_set_attr_value(gl_profile_tab[IMU_PROFILE_APP_ID].char_handle, sizeof(imu_data_val), imu_data_val);
    }


    // ==================== 运动检测状态机处理 ====================
    switch (detector->motion_state) {
    case MOTION_STATE_STABLE:
        // 稳定状态：检测是否开始运动
        if (is_stable(detector, MOTION_MOTION_THRESHOLD)) {
            // 保持稳定，定期更新平均值
            if (detector->window_index % MOTION_AVERAGE_WINDOW_SIZE == 0) {
                imu_calculate_average(detector);
            }
        } else {
            // 检测到运动开始，切换到加速度检测状态
            detector->pass_timing  = 0;
            detector->fail_timing  = 0;
            detector->motion_state = MOTION_STATE_ACCEL_DETECTING;
        }
        break;

    case MOTION_STATE_ACCEL_DETECTING:
        // 加速度检测状态：确认运动开始
        if (is_motion_accel(detector, MOTION_DELTA_ACCEL_THRESHOLD)) {
            // 检测到加速度变化
            if (detector->pass_timing >= MOTION_ACCEL_TIME_MS) {
                // 加速度确认时间达到，运动开始确认
                ESP_LOGI(TAG, "motion confirmed: %d", detector->motion_direct);
                detector->fail_timing  = 0;
                detector->pass_timing  = 0;
                detector->motion_state = MOTION_STATE_WAIT_SLOW;
            }
        } else if (detector->fail_timing >= MOTION_NG_TIME_MS) {
            // 检测失败超时，回到等待稳定状态
            ESP_LOGI(TAG, "detecting timeout");
            detector->fail_timing  = 0;
            detector->pass_timing  = 0;
            detector->motion_state = MOTION_STATE_WAIT_STABLE;
        }
        break;

    case MOTION_STATE_WAIT_SLOW:
        // 等待减速状态：等待运动减速开始
        if (is_motion_slow(detector, MOTION_DELTA_SLOW_THRESHOLD)) {
            // 检测到减速开始
            ESP_LOGI(TAG, "motion res detected: %d", detector->motion_direct);
            detector->fail_timing  = 0;
            detector->pass_timing  = 0;
            detector->motion_state = MOTION_STATE_SLOW_DETECTING;
        } else if (detector->fail_timing >= MOTION_TRANSFER_TIMEOUT_MS) {
            // 等待减速超时
            ESP_LOGI(TAG, "wait slow timeout");
            detector->pass_timing  = 0;
            detector->fail_timing  = 0;
            detector->motion_state = MOTION_STATE_WAIT_STABLE;
        }
        break;

    case MOTION_STATE_SLOW_DETECTING:
        // 减速检测状态：确认运动结束
        if (is_motion_slow(detector, MOTION_DELTA_SLOW_THRESHOLD)) {
            // 检测到减速变化
            if (detector->pass_timing >= MOTION_SLOW_TIME_MS) {
                // 减速确认时间达到，运动结束确认，发送动作信号
                ESP_LOGI(TAG, "motion res confirmed: %d", detector->motion_direct);
                send_paw_action(detector);
                detector->fail_timing  = 0;
                detector->pass_timing  = 0;
                detector->motion_state = MOTION_STATE_WAIT_STABLE;
            }
        } else if (detector->fail_timing >= MOTION_NG_TIME_MS) {
            // 减速检测失败超时
            ESP_LOGI(TAG, "slow detecting timeout");
            detector->fail_timing  = 0;
            detector->pass_timing  = 0;
            detector->motion_state = MOTION_STATE_WAIT_STABLE;
        }
        break;

    case MOTION_STATE_WAIT_STABLE:
        // 等待稳定状态：等待回到稳定状态
        if (is_stable_keep(detector, MOTION_DELTA_SLOW_THRESHOLD)) {
            // 恢复到稳定状态
            ESP_LOGI(TAG, "restore stable");
            detector->pass_timing = 0;
            detector->fail_timing = 0;
            imu_calculate_average(detector);
            detector->motion_state = MOTION_STATE_STABLE;
        }
        break;
    default:
        break;
    }

    // ==================== 翻转检测处理 ====================
    switch (detector->flip_state) {
    case FLIP_POS:
        // 正面朝上状态：检测是否翻转到背面
        if (detector->accel_window[detector->window_index].z < -4096) {
            // Z轴加速度小于-4096（约-0.5g），可能开始翻转
            detector->flip_timing += MOTION_DELTA_TIME_MS;
            if (detector->flip_timing > MOTION_FLIP_TIME_MS
                && detector->accel_window[detector->window_index].z < -0.8 * 8192)
            {
                // 翻转时间超过阈值且Z轴加速度小于-0.8g，确认翻转
                detector->flip_state  = FLIP_NEG;
                detector->flip_timing = 0;
                ESP_LOGI(TAG, "flip detected: %d", detector->flip_state);
                send_paw_action(detector);
            }
        } else {
            detector->flip_timing = 0; // 重置翻转计时器
        }
        break;

    case FLIP_NEG:
        // 正面朝下状态：检测是否翻转到正面
        if (detector->accel_window[detector->window_index].z > 4096) {
            // Z轴加速度大于4096（约0.5g），可能开始翻转
            detector->flip_timing += MOTION_DELTA_TIME_MS;
            if (detector->flip_timing > MOTION_FLIP_TIME_MS
                && detector->accel_window[detector->window_index].z > 0.8 * 8192)
            {
                // 翻转时间超过阈值且Z轴加速度大于0.8g，确认翻转
                detector->flip_state  = FLIP_POS;
                detector->flip_timing = 0;
                ESP_LOGI(TAG, "flip detected: %d", detector->flip_state);
                send_paw_action(detector);
            }
        } else {
            detector->flip_timing = 0; // 重置翻转计时器
        }
        break;
    default:
        break;
    }

    // 更新滑动窗口索引
    detector->window_index = (detector->window_index + 1) % MOTION_DETECT_SAMPLES;
}

/**
 * @brief 动作响应任务
 * @param arg 任务参数
 *
 * 该任务负责根据检测到的手掌动作执行相应的反馈：
 * - 翻转动作：三个马达同时振动1秒
 * - 向左移动：马达1→马达2→马达3依次振动
 * - 向右移动：马达3→马达2→马达1依次振动
 * - 向前移动：雾化器喷雾1秒
 */
void action_respone_task(void *arg)
{
    // 初始化雾化器1
    atomizer1.atomizer_gpio = ATOMIZER1_GPIO;
    atomizer1.freq = ATOMIZER1_LEDC_FREQ_HZ;
    atomizer1.ledc_timer = ATOMIZER1_LEDC_TIMER;
    atomizer1.ledc_channel = ATOMIZER1_LEDC_CHANNEL;
    atomizer1.duty_rate = ATOMIZER1_DUTY_RATE;
    ESP_ERROR_CHECK(atomizer_init(&atomizer1));

    // 初始化三个振动马达
    ESP_ERROR_CHECK(app_motor_init());

    // 创建动作信号量
    paw_action_sem = xSemaphoreCreateBinary();
    if (paw_action_sem == NULL) {
        ESP_LOGE(TAG, "failed to create paw action semaphore");
        return;
    }

    // 创建运动检测定时器，每20ms执行一次检测
    esp_timer_create_args_t motion_detect_timer_args = {
        .callback        = &motion_detect_callback,
        .arg             = &motion_detector,
        .dispatch_method = ESP_TIMER_TASK,
        .name            = "motion_detect_timer"};
    ESP_ERROR_CHECK(esp_timer_create(&motion_detect_timer_args, &motion_detect_timer));
    ESP_ERROR_CHECK(esp_timer_start_periodic(motion_detect_timer, MOTION_DELTA_TIME_MS * 1000)); // 20ms周期

    // 主循环：等待动作信号并执行相应反馈
    while (1) {
        // 等待动作信号
        xSemaphoreTake(paw_action_sem, portMAX_DELAY);

        // 根据检测到的动作类型执行相应反馈
        switch (paw_state) {
        case PAW_ACTION_FLIP:
            xTaskNotify(motor_control_task_handle, MOTOR_ACTON_BOTH, eSetValueWithOverwrite);
            break;
        case PAW_ACTION_LEFT:
            xTaskNotify(motor_control_task_handle, MOTOR_ACTON_POS, eSetValueWithOverwrite);
            break;
        case PAW_ACTION_RIGHT:
            xTaskNotify(motor_control_task_handle, MOTOR_ACTON_NEG, eSetValueWithOverwrite);
            break;
        case PAW_ACTION_FORWARD:
            // 向前移动：雾化器喷雾1秒
            atomizer_on(&atomizer1);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            atomizer_off(&atomizer1);
            break;

        default:
            break;
        }
    }
}

/**
 * @brief 应用程序主函数
 *
 * 系统初始化入口，负责：
 * 1. 初始化IMU传感器
 * 2. 初始化LED指示灯
 * 3. 创建电池电压检测定时器
 * 4. 创建动作响应任务
 */
void app_main(void)
{
    esp_err_t ret;
    esp_log_level_set(TAG, ESP_LOG_INFO);

    ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    // 初始化SC7A20H IMU传感器
    sc7a20h_i2c_init(I2C_NUM_0);
    sc7a20h_init();

    // 初始化电池电压LED指示灯
    ESP_ERROR_CHECK(batvol_led_init());

    // 初始化电池电压检测定时器
    ESP_ERROR_CHECK(batvol_monitor_init());
    
    ESP_ERROR_CHECK(ble_init());

    ESP_LOGI(TAG, "paw action respone task created");

    // 创建动作响应任务
    bool success = xTaskCreate(action_respone_task, "action_respone_task", 3072, NULL, 5, NULL);
    if (!success) {
        ESP_LOGE(TAG, "failed to create paw action respone task");
        return;
    }

    // int16_t x, y, z;
    // while (1) {
    //     sc7a20h_read_accel(&x, &y, &z);
    //     printf("x: %d, y: %d, z: %d\n", x, y, z);
    //     vTaskDelay(200 / portTICK_PERIOD_MS);
    // }

    // atomizer_t atomizer1 = {
    //     .atomizer_gpio = ATOMIZER1_GPIO,
    //     .freq          = ATOMIZER1_LEDC_FREQ_HZ,
    //     .ledc_timer    = ATOMIZER1_LEDC_TIMER,
    //     .ledc_channel  = ATOMIZER1_LEDC_CHANNEL,
    //     .duty_rate     = ATOMIZER1_DUTY_RATE};
    // ESP_ERROR_CHECK(atomizer_init(&atomizer1));
    // while (1) {
    //     atomizer_on(&atomizer1);
    //     ESP_LOGI(TAG, "atomizer on: %f", atomizer1.duty_rate);
    //     vTaskDelay(1000 / portTICK_PERIOD_MS);
    //     atomizer_duty_rate_set(&atomizer1, 0.4);
    //     atomizer_on(&atomizer1);
    //     ESP_LOGI(TAG, "atomizer on: %f", atomizer1.duty_rate);
    //     vTaskDelay(1000 / portTICK_PERIOD_MS);
    //     atomizer_duty_rate_set(&atomizer1, 0.5);
    //     atomizer_on(&atomizer1);
    //     ESP_LOGI(TAG, "atomizer on: %f", atomizer1.duty_rate);
    //     vTaskDelay(1000 / portTICK_PERIOD_MS);
    //     atomizer_duty_rate_set(&atomizer1, 0.6);
    //     atomizer_on(&atomizer1);
    //     ESP_LOGI(TAG, "atomizer on: %f", atomizer1.duty_rate);
    //     vTaskDelay(1000 / portTICK_PERIOD_MS);
    //     atomizer_duty_rate_set(&atomizer1, 0.7);
    //     atomizer_on(&atomizer1);
    //     ESP_LOGI(TAG, "atomizer on: %f", atomizer1.duty_rate);
    //     vTaskDelay(1000 / portTICK_PERIOD_MS);
    //     atomizer_duty_rate_set(&atomizer1, 1);
    //     atomizer_on(&atomizer1);
    //     ESP_LOGI(TAG, "atomizer on: %f", atomizer1.duty_rate);
    //     vTaskDelay(1000 / portTICK_PERIOD_MS);
    //     atomizer_off(&atomizer1);
    //     ESP_LOGI(TAG, "atomizer off");
    //     vTaskDelay(1000 / portTICK_PERIOD_MS);
    // }
}
